//
//  AstExpr.h
//  LightBasic
//
//  Created by Albert on 02/04/2011.
//  Copyright 2011 LightBasic Development Team. All rights reserved.
//
#pragma once


/**
 * Base class for expressions
 */
struct AstExpression : Ast
{
    /// Expression type (don't own!)
    Type * type;
    
    /// is constant expression ?
    virtual bool IsConst() { return false; }
    
    /// Create new expression
    AstExpression() : type(NULL) {};
};


/**
 * list of expressions
 */
struct AstExprList : Ast
{
    /// Expression container
    typedef std::vector<AstExpression *> List;
    
    /// expressions
    List exprs;
    
    /// Declare this ast node
    DECLARE_AST();
    
    /// clean list
    virtual ~AstExprList()
    {
        for (List::iterator iter = exprs.begin(); iter != exprs.end(); iter++) {
            delete *iter;
        }
    }
};


/**
 * Unary expression
 */
struct AstExprUnary : AstExpression
{
    /// operator token
    Token * op;
    
    /// expression
    AstExpression * lhs;
    
    /// check if expression is constant
    virtual bool IsConst() { return lhs->IsConst(); }
    
    /// create unary expression
    AstExprUnary(Token * op, AstExpression * lhs) : op(op), lhs(lhs) {}
    
    /// Declare this ast node
    DECLARE_AST();
    
    // release operator
    virtual ~AstExprUnary()
    {
        if (op != NULL) delete op;
        if (lhs != NULL) delete lhs;
    }
};


/**
 * Binary expression
 */
struct AstExprBinary : AstExpression
{
    /// operator token
    Token * op;
    
    /// expression
    AstExpression * lhs, * rhs;
    
    /// check if expression is constant
    virtual bool IsConst() { return lhs->IsConst() && rhs->IsConst(); }
    
    /// create unary expression
    AstExprBinary(Token * op, AstExpression * lhs, AstExpression * rhs) : op(op), lhs(lhs), rhs(rhs) {}
    
    /// Declare this ast node
    DECLARE_AST();
    
    // release operator
    virtual ~AstExprBinary()
    {
        if (op != NULL) delete op;
        if (lhs != NULL) delete lhs;
        if (rhs != NULL) delete rhs;
    }

};


/**
 * Identifier
 */
struct AstExprIdent : AstExpression
{
    /// Token reference
    Token * token;
    
    /// construct
    AstExprIdent(Token * token) : token(token) {}
    
    /// Declare this ast node
    DECLARE_AST();
    
    // release token
    virtual ~AstExprIdent()
    {
        if (token != NULL) delete token;
    }
};


/**
 * Constant number
 */
struct AstExprNumber: AstExpression
{
    /// Token reference
    Token * token;
    
    /// is constant expression ?
    virtual bool IsConst() { return true; }
    
    /// construct
    AstExprNumber(Token * token) : token(token) {}
    
    /// Declare this ast node
    DECLARE_AST();
    
    // release token
    virtual ~AstExprNumber()
    {
        if (token != NULL) delete token;
    }
};


/**
 * String literal
 */
struct AstExprString : AstExpression
{
    /// Token reference
    Token * token;
    
    /// is constant expression ?
    virtual bool IsConst() { return true; }
    
    /// construct
    AstExprString(Token * token) : token(token) {}
    
    /// Declare this ast node
    DECLARE_AST();
    
    // release token
    virtual ~AstExprString()
    {
        if (token != NULL) delete token;
    }
};
